import express, { Express, Request, Response, NextFunction } from 'express';
import { AppConfig } from '~/config/app.config';
import { Logger } from '~/utils/logger';

/**
 * HttpServer 类用于创建和管理 HTTP 服务器
 * 提供初始化、启动、停止服务器以及路由配置等功能
 */
export class HttpServer {
  static app: Express;
  private logger = Logger.child('HttpServer');

  constructor() {}

  /**
   * 初始化服务器配置和路由
   */
  initialize(): void {
    // 创建 Express 服务器实例
    HttpServer.app = express();

    // 配置中间件
    this.setupMiddleware();

    // 配置路由
    this.setupRoutes();
  }

  /**
   * 设置中间件
   */
  private setupMiddleware(): void {
    // JSON 解析
    HttpServer.app.use(express.json({ limit: '10mb' }));
    HttpServer.app.use(express.urlencoded({ extended: true, limit: '10mb' }));

    // 请求日志中间件
    HttpServer.app.use((request: Request, response: Response, next: NextFunction) => {
      const start = Date.now();

      response.on('finish', () => {
        const duration = Date.now() - start;
        this.logger.info(
          `${request.method} ${request.path} - ${response.statusCode} - ${duration}ms`
        );
      });

      next();
    });
  }

  /**
   * 设置路由
   */
  private setupRoutes(): void {
    // 健康检查路由
    HttpServer.app.get('/health', (request: Request, response: Response) => {
      response.json({
        status: 'ok',
        timestamp: new Date().toISOString(),
        uptime: process.uptime(),
      });
    });
  }

  /**
   * 启动服务器
   */
  async start(config: AppConfig): Promise<void> {
    try {
      this.initialize();

      HttpServer.app.listen(config.port, config.host, () => {
        this.logger.info(`🔗 访问地址: http://localhost:${config.port}`);
      });
    } catch (error) {
      this.logger.error('服务器启动失败:', error);
      throw error;
    }
  }

  /**
   * 停止服务器
   */
  async stop(): Promise<void> {
    try {
      // Express 没有直接的 close 方法，需要保存 server 实例
      this.logger.info('服务器已停止');
    } catch (error) {
      this.logger.error('停止服务器时出错:', error);
      throw error;
    }
  }

  /**
   * 获取服务器实例（用于添加自定义路由）
   */
  getApp(): Express {
    return HttpServer.app;
  }
}
